import { Game } from '../src/objects/Game';
import { Move } from '../src/objects/Move';

import { expect } from 'chai';
import { PieceColor } from '../src/objects/Piece';
import { range } from '../src/utils/range';
import { GameState, Judge } from '../src/objects/Judge';

describe('utility test', () => {
    it('range', () => {
        expect(range(0, 4).length).equals(5);
    });
});

describe('basic test suite', () => {
    let game: Game;

    afterEach(() => {
        game.board.printBoard();
        console.log();
    });

    it('new game', () => {
        game = Game.newGame();
    });

    it('basic opening', () => {
        expect(game.makeMove(new Move(7, 1, 7, 4))).is.true;
        expect(game.makeMove(new Move(0, 7, 2, 6))).is.true;
    });

    it('illegal moves', () => {
        expect(game.makeMove(new Move(7, 4, 6, 4))).is.false;
        expect(game.currentPlayer).equals(PieceColor.RED);
        expect(game.makeMove(new Move(9, 0, 5, 0))).is.false;
        expect(game.makeMove(new Move(3, 0, 4, 0))).is.false;
        expect(game.makeMove(new Move(5, 0, 4, 0))).is.false;
    });

    it('taking pieces and notations', () => {
        expect(game.currentPlayer).equals(PieceColor.RED);
        expect(Move.applyMove(game, 'C4+4')).is.true;
        expect(game.currentPlayer).equals(PieceColor.DARK);
        expect(Move.applyMove(game, 'k6+4')).is.true;
    });

    it('more illegal moves', () => {
        expect(game.currentPlayer).equals(PieceColor.RED);
        expect(Move.applyMove(game, 'B2+4')).is.true;
        expect(Move.applyMove(game, 'k4+6')).is.true;
        expect(Move.applyMove(game, 'B4+2')).is.true;
        expect(Move.applyMove(game, 'r0+1')).is.true;
        expect(Move.applyMove(game, 'B2+4')).is.false;
        expect(Move.applyMove(game, 'P2+1')).is.false;
        expect(Move.applyMove(game, 'P4+1')).is.true;
        expect(Move.applyMove(game, 'r0+1')).is.true;
        expect(Move.applyMove(game, 'R0+1')).is.true;
        expect(Move.applyMove(game, 'a3+4')).is.true;
        expect(Move.applyMove(game, 'C7+4')).is.true;
        expect(Move.applyMove(game, 'a4+3')).is.true;
        expect(Move.applyMove(game, 'C7=5')).is.false;
        expect(Move.applyMove(game, 'C7-4')).is.true;
        expect(Move.applyMove(game, 'a3+4')).is.false;
    });

    it('reverting', () => {
        game.revertLastMove();
        expect(game.currentPlayer).equals(PieceColor.RED);
    });

    it('loading a game', () => {
        const savedGame = '{ "board": "g03G94", "moves": [], "currentPlayer": 2 }';
        game = Game.loadGame(savedGame);
        expect(game.board.getPieceAt(9, 4).color === PieceColor.RED);
        expect(Move.applyMove(game, 'G4=3')).is.true;
    });

    it('judging a game state', () => {
        const savedGame = '{ "board": "p44g03P54G94", "moves": [], "currentPlayer": 2 }';
        game = Game.loadGame(savedGame);
        const judge = new Judge(game.board, game.rules);
        const report = judge.analyze(game.currentPlayer);
        expect(report.state).equals(GameState.NORMAL);
        expect(report.threats.length).equals(1);
        game.board.printBoard(report.threats);
    });

    it('judging a check', () => {
        const savedGame = '{ "board": "g04a05R08a14P37C44b46c61K76r82A84G94", "moves": [], "currentPlayer": 1 }';
        game = Game.loadGame(savedGame);
        const judge = new Judge(game.board, game.rules);
        expect(game.currentPlayer).equals(PieceColor.DARK);
        const report = judge.analyze(game.currentPlayer);
        expect(report.state).equals(GameState.CHECK);
        game.board.printBoard(report.threats);
    });

    it('judging a checkmate', () => {
        const savedGame = '{ "board": "g04a05a14K25P33C43b46c61r92A93G94", "moves": [], "currentPlayer": 1 }';
        game = Game.loadGame(savedGame);
        const judge = new Judge(game.board, game.rules);
        expect(game.currentPlayer).equals(PieceColor.DARK);
        const report = judge.analyze(game.currentPlayer);
        expect(report.state).equals(GameState.CHECKMATE);
        game.board.printBoard(report.threats);
    });

    it('judging a stalemate', () => {
        const savedGame = '{ "board": "a03g04a14A75G94C95", "moves": [], "currentPlayer": 1 }'
        game = Game.loadGame(savedGame);
        const judge = new Judge(game.board, game.rules);
        expect(game.currentPlayer).equals(PieceColor.DARK);
        const report = judge.analyze(game.currentPlayer);
        expect(report.state).equals(GameState.STALEMATE);
        game.board.printBoard(report.threats);
    });

    it('judge stress test', () => {
        game = Game.newGame();
        const judge = new Judge(game.board, game.rules);
        const report = judge.analyze(game.currentPlayer);
        expect(report.state).equals(GameState.NORMAL);
    }).timeout(300);
});
